#include <iostream>
#include <sstream>
#include <thread>
#include <atomic>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <cstring>
#include "../log/ckflog.hpp"
#include "log_tester.hpp"

void test_date()
{
    ckflogs::FormatItem *fi = new ckflogs::DateFormatItem("%Y-%M-%D %H:%m:%S");
    ckflogs::LogMessage msg(ckflogs::LogLevel::Value::DEBUG, "test.cc", 40, "日志器A", "测试日志");
    std::ostringstream oss;
    fi->outputItem(oss, msg);
    std::cout << oss.str() << std::endl;
    std::cout << msg.tid_ << std::endl;
}
void test_fmt()
{
    // ckflogs::Formatter fmt("[%d{%Y-%M-%D %H:%m:%S}][%L][%t][%c][%f:%l]%T%m%n");
    ckflogs::Formatter fmt("format %d %c}%T[test log]%n");

    ckflogs::LogMessage msg1(ckflogs::LogLevel::Value::DEBUG, __FILE__, __LINE__, "logger1", "测试日志1");
    ckflogs::LogMessage msg2(ckflogs::LogLevel::Value::DEBUG, __FILE__, __LINE__, "logger2", "测试日志2");
    ckflogs::LogMessage msg3(ckflogs::LogLevel::Value::DEBUG, __FILE__, __LINE__, "logger3", "测试日志3");

    fmt.formatTo(std::cout, msg1);
    fmt.formatTo(std::cout, msg2);
    fmt.formatTo(std::cout, msg3);
}
void test_sink()
{
    ckflogs::Formatter fmt;
    ckflogs::LogMessage msg(ckflogs::LogLevel::Value::DEBUG, __FILE__, __LINE__, "logger1", "测试日志1");
    std::string str = fmt.format(msg);
    ckflogs::LogSinker::Ptr log_sinker = ckflogs::LogSinkerFactory::create<ckflogs::RollBySizeLogSinker>("123/456/789/bash-", 1024 * 1024 * 2);
    size_t size = 0;
    while (size < 10 * ckflogs::default_max_size)
    {
        log_sinker->sink(str.c_str(), str.size());
        size += str.size();
    }
}

void test_logger()
{
    ckflogs::LoggerBuilder::Ptr builder1 = ckflogs::LoggerBuilderFactory::create<ckflogs::LocalLoggerBuilder>();
    builder1->bulidType(ckflogs::Logger::LoggerType::LOGGER_ASYNC);
    builder1->bulidName("Asynclogger");
    builder1->bulidLevel(ckflogs::LogLevel::Value::WARN);
    builder1->buildFormatter("[%d{%H:%m:%S}][%L][%c][%f:%l]%T%m%n");
    // builder1->buildSinker<ckflogs::StdOutLogSinker>();
    builder1->buildSinker<ckflogs::FileLogSinker>("logfile1/test.log");
    builder1->buildSinker<ckflogs::RollBySizeLogSinker>("logfile1/rollfiles/bash-");
    ckflogs::Logger::Ptr logger1 = builder1->build();

    ckflogs::LoggerBuilder::Ptr builder2 = ckflogs::LoggerBuilderFactory::create<ckflogs::LocalLoggerBuilder>();
    builder2->bulidType(ckflogs::Logger::LoggerType::LOGGER_ASYNC);
    builder2->bulidName("Asynclogger");
    builder2->bulidLevel(ckflogs::LogLevel::Value::WARN);
    builder2->buildFormatter("[%d{%H:%m:%S}][%L][%c][%f:%l]%T%m%n");
    // builder2->buildSinker<ckflogs::StdOutLogSinker>();
    builder2->buildSinker<ckflogs::FileLogSinker>("logfile2/test.log");
    builder2->buildSinker<ckflogs::RollBySizeLogSinker>("logfile2/rollfiles/bash-");
    builder2->buildAsycnType("SAFE");
    ckflogs::Logger::Ptr logger2 = builder2->build();

    ckflogs::LoggerBuilder::Ptr builder3 = ckflogs::LoggerBuilderFactory::create<ckflogs::LocalLoggerBuilder>();
    builder3->bulidType(ckflogs::Logger::LoggerType::LOGGER_ASYNC);
    builder3->bulidName("Asynclogger");
    builder3->bulidLevel(ckflogs::LogLevel::Value::WARN);
    builder3->buildFormatter("[%d{%H:%m:%S}][%L][%c][%f:%l]%T%m%n");
    // builder2->buildSinker<ckflogs::StdOutLogSinker>();
    builder3->buildSinker<ckflogs::FileLogSinker>("logfile3/test.log");
    builder3->buildSinker<ckflogs::RollBySizeLogSinker>("logfile3/rollfiles/bash-");
    builder3->buildAsycnType("UNSAFE");
    ckflogs::Logger::Ptr logger3 = builder3->build();

    long long count = 0;
    // logger->debug(__FILE__, __LINE__, "%s-%d", "hello", count++);
    // logger->info(__FILE__, __LINE__, "%s-%d", "hello", count++);
    // logger->warn(__FILE__, __LINE__, "%s-%d", "hello", count++);
    // logger->error(__FILE__, __LINE__, "%s-%d", "hello", count++);
    // logger->fatal(__FILE__, __LINE__, "%s-%d", "hello", count++);
    std::atomic<size_t> size(0);

    clock_t b1 = clock();
    while (size < 10 * 1024 * 1024)
    {
        int n = logger1->error(__FILE__, __LINE__, "%s-%d", "hello", count++);
        size += n;
    }
    clock_t e1 = clock();

    size = 0;
    clock_t b2 = clock();
    while (size < 10 * 1024 * 1024)
    {
        int n = logger2->error(__FILE__, __LINE__, "%s-%d", "hello", count++);
        size += n;
    }
    clock_t e2 = clock();

    size = 0;
    clock_t b3 = clock();
    while (size < 10 * 1024 * 1024)
    {
        int n = logger3->error(__FILE__, __LINE__, "%s-%d", "hello", count++);
        size += n;
    }
    clock_t e3 = clock();

    std::cout << "同步日志器效率：" << e1 - b1 << std::endl;
    std::cout << "异步日志器(Safe)效率：" << e2 - b2 << std::endl;
    std::cout << "异步日志器(Unsafe)效率：" << e3 - b3 << std::endl;
}

void test_g_logger()
{
    // ckflogs::Logger::Ptr logger = ckflogs::LoggerManager::getInstance().getLogger("Asynclogger");
    ckflogs::Logger::Ptr logger = ckflogs::getLogger("Asynclogger");
    if (logger.get() == nullptr)
    {
        std::cout << "Logger not exist!" << std::endl;
        abort();
    }

    long long count = 0;
    // logger->debug(__FILE__, __LINE__, "%s-%d", "hello", count++);
    // logger->info(__FILE__, __LINE__, "%s-%d", "hello", count++);
    // logger->warn(__FILE__, __LINE__, "%s-%d", "hello", count++);
    // logger->error(__FILE__, __LINE__, "%s-%d", "hello", count++);
    // logger->fatal(__FILE__, __LINE__, "%s-%d", "hello", count++);
    logger->debug("%s-%d", "hello", count++);
    logger->info("%s-%d", "hello", count++);
    logger->warn("%s-%d", "hello", count++);
    logger->error("%s-%d", "hello", count++);
    logger->fatal("%s-%d", "hello", count++);

    // 以文件大小的尺度落地日志
    // while (size < 10 * 1024 * 1024)
    // {
    //     int n = logger->error(__FILE__, __LINE__, "%s-%d", "hello", count++);
    //     size += n;
    // }

    // 以时间长短的尺度落地日志
    // time_t start = ckflogs::util::Date::now();
    // time_t end = start + 5;
    // while (ckflogs::util::Date::now() < end)
    // {
    //     logger->error(__FILE__, __LINE__, "%s-%d", "hello log", count++);
    // }

    DF_DEBUG("%s-%d", "hello", count++);
    DF_INFO("%s-%d", "hello", count++);
    DF_WARN("%s-%d", "hello", count++);
    DF_ERROR("%s-%d", "hello", count++);
    DF_FATAL("%s-%d", "hello", count++);
}

int main()
{
    ckflogs::LoggerBuilder::Ptr builder = std::make_shared<ckflogs::GlobalLoggerBuilder>();
    builder->buildSinker<ckflogs::FileLogSinker>("logfile/test.log");

    builder->bulidType(ckflogs::Logger::LoggerType::LOGGER_SYNC);
    builder->bulidName("Synclogger");
    builder->build();
    ckflogs::LogTester::test("Synclogger", 1000000, 10, 1);
    ckflogs::LogTester::test("Synclogger", 1000000, 10, 3);

    builder->bulidType(ckflogs::Logger::LoggerType::LOGGER_ASYNC);
    builder->bulidName("Asynclogger");
    builder->buildAsycnType("UNSAFE");
    builder->build();
    ckflogs::LogTester::test("Asynclogger", 1000000, 10, 1);
    ckflogs::LogTester::test("Asynclogger", 1000000, 10, 3);


    return 0;
}